﻿using System;
using System.Collections.Generic;
using OpenNETCF.Win32.Notify;

namespace svs.Mobile.BeyondScheduler.Core.Objects
{
	internal class SchedulingMethodSetUserNotification : ISchedulingMethod
	{
		#region IDeviceScheduling Members

		public void UpdateScheduledTasks(Dictionary<string, ScheduledTask> tasks)
		{
			int[] handles = Notify.GetUserNotificationHandles();

			foreach (int i in handles)
			{
				try
				{
					UserNotificationInfoHeader h = Notify.GetUserNotification(i);

					ScheduledTask task = GetTaskByTrigger(h.UserNotificationTrigger, tasks);
					if (task != null)
					{
						if (!task.Event.ExistOnDevice)
						{
							task.Event.EventHandle = h.Handle;
							task.Event.ActualStartTime = h.UserNotificationTrigger.StartTime;
						}
						else
						{
							DeleteOrphanedNotification(i);
						}
					}
					else
					{
						if (IsOurNotification(h.UserNotificationTrigger))
						{
							DeleteOrphanedNotification(i);
						}
					}
				}
				catch (Exception ex)
				{
					CoreHelper.WriteLogEntry("Unable to read task!. Reason: " + ex.Message);
				}
			}
		}

		public void DeleteScheduledTaskFromDevice(ScheduledTask task)
		{
			if (task.Event.EventHandle != 0)
			{
				CoreHelper.WriteLogEntry(string.Format("Deleting scheduled run for Task: {0}", task));
				if (!Notify.ClearUserNotification(task.Event.EventHandle))
				{
					CoreHelper.WriteLogEntry(
						string.Format("Unable to delete old Handle for: {0}", task));
				}
				else
				{
					task.Event.EventHandle = 0;
					task.Event.ActualStartTime = null;
				}
			}
		}

		public void SetScheduledTaskToDevice(ScheduledTask task)
		{
			if (task.Event == null)
				throw new ArgumentException("Task event can't be null!");

			if (!task.Active)
			{
				CoreHelper.WriteLogEntry(
					string.Format("Task {0} is INACTIVE!", task));
				return;
			}

			if (!task.Event.OccursInTheFuture)
			{
				CoreHelper.WriteLogEntry(
					string.Format("Task {0} has no Recurrence!", task));
				return;
			}

			UserNotificationTrigger trg = task.Event.GetNotificationTrigger(task.TaskID);

			if (trg != null)
			{
				UserNotification un = new UserNotification();
				un.Action = NotificationAction.Vibrate;

				task.Event.EventHandle = Notify.SetUserNotification(trg, un);
				task.Event.ActualStartTime = trg.StartTime;
				task.Event.UnadjustedStartTime = trg.StartTime;

				CoreHelper.WriteLogEntry(
					string.Format("Set Notification For: {0}", task));
			}
			else
			{
				CoreHelper.WriteLogEntry(
					string.Format("Unable to set Notification For: {0}", task));
			}
		}

		#endregion

		private static ScheduledTask GetTaskByTrigger(UserNotificationTrigger trigger, Dictionary<string, ScheduledTask> tasks)
		{
			if (trigger == null)
				return null;

			//First find by argument
			if (!string.IsNullOrEmpty(trigger.Arguments) && !string.IsNullOrEmpty(trigger.Application))
			{
				ScheduledTask task = TaskRepository.GetTaskById(trigger.Arguments);
				if (task != null && task.Event.GetNotificationTrigger(task.TaskID).Application == trigger.Application)
					return task;
			}

			//Then find based on the event name
			foreach (KeyValuePair<string, ScheduledTask> pair in tasks)
			{
				if (pair.Value.Event.IsFor(trigger.Application))
					return pair.Value;
			}

			return null;
		}

		private static bool IsOurNotification(UserNotificationTrigger trigger)
		{
			if (trigger != null && !string.IsNullOrEmpty(trigger.Application))
			{
				if (String.Compare(trigger.Application, Configuration.SheduleRunnerPath, true) == 0)
					return true;

				if (trigger.Application.IndexOf("MobileScheduler.exe", StringComparison.CurrentCultureIgnoreCase) > 0)
					return true;
			}

			return false;
		}

		private static void DeleteOrphanedNotification(int i)
		{
			CoreHelper.WriteLogEntry("Deleted orphaned notification for: " + i);
			Notify.ClearUserNotification(i);
		}
	}
}